#Keep the directory structure if you don't want to give filenames to the api calls

from mesh_node import *
from parse_mesh import *
from parse_dump import *

class mesh():
	"""Requires mesh files if the default files are not present"""
	def __init__(self, mesh_filename='MESH/ascii/mtrees2007.bin', dump_filename='dump', des_filename='MESH/ascii/d2007.bin'):
		self.mesh_filename = mesh_filename
		self.dump_filename = dump_filename
		self.des_filename = des_filename
		self.invert = None
		self.des_file = open(self.des_filename, 'r')
		self.entries = {}
		self.generate_entries()
		
	def generate_entries(self):
		"""Reads the files and creates a hash table"""
		try:
			f = open(self.dump_filename, 'r')
			f.close()
			print 'Found dump file'
			dump = parse_dump(self.dump_filename, self.des_filename)
			dump.parse()
			self.entries = dump.entries
		except IOError:
			print 'Could not find dump file, creating'
			parse = parse_mesh_text(self.mesh_filename)
			parse.create_table()
			parse.put_linenos(self.des_filename)
			parse.dump_table(self.dump_filename)
			self.entries = parse.entries

	def generate_description(self, node):
		"""Obvious"""
		self.des_file.seek(int(node.des_pos))
		des = self.extract_description()
		return des
	
	def extract_description(self):
		"""Takes a record and extracts the description string from there"""
		while True:
			line = self.des_file.readline()[:-1]
			if not line:
				return None
			if line[:3] == 'MS ':
				entries = line.split('=')
				des = entries[1].strip()
				return des
			
	def lookup_id(self, id):
		"""Gives a mesh node object corresponding to the id given"""
		if self.entries == {}:
			print "No entries"
		try:
			node = self.entries[id]
			node.description = self.generate_description(node)
			return node
		except KeyError:
			return None

	def lookup_name(self, name):
		"""Gives a list of mesh nodes corresponding to the name given"""
		if not self.invert:
			self.invert_dict()
		try:
			nodelist = self.invert[name]
			for node in nodelist:
				node.description = self.generate_description(node)
			return nodelist
		except KeyError:
			return None
		
	def invert_dict(self):
		"""Takes the entries with id as the key and returns a new dict with names as the key
		Returns a special dictionary whose value for any key is a list"""
		self.invert = mdict()
		for (id, node) in self.entries.items():
			self.invert[node.name] = node
			
	def __getitem__(self, key):
		"""Tries to guess what you are looking for and looks up"""
		if len(key) == 3 or '.' in key:
			return self.lookup_id(key)
		else:
			return self.lookup_name(key)
			
if __name__ == '__main__':
	#m = mesh(dump_filename = 'dump', des_filename = 'MESH/ascii/d2007.bin')
	# print m.lookup_id('D12.776.124.486.485.705.750.530.500').description
	# print m.lookup_id('C16.320.565.300.281').description
	# print m.lookup_name('Dystonia Musculorum Deformans')[0].description
	# print m.lookup_name('Mammary Glands, Human')[0].description
	m = mesh()
	#lookup for an id
	print m['C16.320.565.300.281'], '\n' 
	#lookup for a name gives list of id's as one name can have more than one sense
	print m['Dystonia Musculorum Deformans'][0].description
	#check mesh_node.py for the things contained in mesh_node object
	